package org.vectrics.batch;

import java.util.Calendar;
import java.util.Date;

import org.apache.log4j.Logger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.vectrics.SystemException;
import org.vectrics.common.util.DateSync;
import org.vectrics.hibernate.ApplicationContext;

public abstract class VectricsQuartzScheduler {
	private Logger log = Logger.getLogger(this.getClass());
	private ApplicationContext applicationContext = null;

	public VectricsQuartzScheduler(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}
	
	public ApplicationContext getApplicationContext() {
		return(this.applicationContext);
	}

	public abstract String getJobName();
	
	public abstract long getSecondsInterval();
	public abstract int getSecondsUntilStart();
	
	
	public abstract Class getJobClass();
	/**
	 * Starts the scheduler for finding job agents needing update.
	 */
	public final void start() {
		try {	
			log.debug("Schedule Batch Job");
			
			String triggerName = getJobName() + " trigger";
			String groupName = this.getApplicationContext().getName();
			String jobName = this.getJobName();
			
			SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
			Scheduler sched = schedFact.getScheduler();
			sched.deleteJob(jobName, groupName);
			
			Trigger trigger = sched.getTrigger(triggerName, groupName);   
			//"0 0/5 14 * * ?"    Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day 		
			//trigger = new CronTrigger(triggerName, group, "0 0/5 14 * * ?");
			Calendar startTime = Calendar.getInstance();
			startTime.setTime(DateSync.getCurrentTime());
			startTime.add(Calendar.SECOND, getSecondsUntilStart());
			
			trigger = new SimpleTrigger(triggerName,
                    Scheduler.DEFAULT_GROUP,
                    startTime.getTime(),
                    null,
                    SimpleTrigger.REPEAT_INDEFINITELY,
                    getSecondsInterval() * 1000L 			// 5 minutes
                    //30 * 60L * 1000L 			// 30 minutes
                    //1L * 60L * 60L * 1000L 			// 1 Hours
                    );
			
			
			JobDetail jobDetail = sched.getJobDetail(this.getClass().getName(),
                    Scheduler.DEFAULT_GROUP);
			
			
			sched.start();
			if (jobDetail == null) {
			    jobDetail = new JobDetail(jobName,
	                                      groupName,
                                     getJobClass());
			    jobDetail.getJobDataMap().put("application.context", this.getApplicationContext());
	 			sched.scheduleJob(jobDetail, trigger);
			}
			
			jobDetail.setDescription("Job Agent Processing");
			jobDetail.setGroup(groupName);
			Date date = trigger.getFireTimeAfter(new Date());
			
			log.info("*** Scheduled Quartz Job" +
					"\r\n - Application:          " + this.getApplicationContext().getName() + 
					"\r\n - Job Name:             " + jobName + 
					"\r\n - Class:                " + getJobClass().getName() +
					"\r\n - Next fire time:       " + date +
					"\r\n - Seconds until start:  " + this.getSecondsUntilStart() +
					"\r\n - Seconds interval:     " + this.getSecondsInterval()
					);
			
	
		} catch (Exception ex) {
			log.error("Exception starting job agent schedule", ex);
			throw new SystemException("Exception starting job agent schedule", ex);
		}
	}
	
}
